package com.cqrt.aop;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqrt.constant.RTErrorCodeEnum;
import com.cqrt.constant.RTPlmConstant;
import com.cqrt.entity.RTKnowTempDocDO;
import com.cqrt.mapper.*;
import com.cqrt.service.RTProjectKnowledgeLinkService;
import com.cqrt.service.RTProjectTemplateService;
import com.cqrt.util.ProjectCodeGenerator;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.pdm.container.model.vo.search.ProjectEntityVO;
import com.hustcad.plm.pdm.core.base.EntityBase;
import com.hustcad.plm.pdm.core.context.TyppmUser;
import com.hustcad.plm.pdm.core.handle.exception.SystemErrorCodeEnum;
import com.hustcad.plm.pdm.core.response.TyppmResponseResult;
import com.hustcad.plm.pdm.enumeration.mapper.TyplmEnumerationItemMapper;
import com.hustcad.plm.pdm.enumeration.model.vo.EnumerationItemHandleVO;
import com.hustcad.plm.pdm.iba.model.dto.IBAQueryDTO;
import com.hustcad.plm.pdm.iba.model.dto.IBASaveParamDTO;
import com.hustcad.plm.pdm.iba.model.dto.SaveObjIBADTO;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeValueService;
import com.hustcad.plm.pdm.iba.service.TyplmCommonAttributeService;
import com.hustcad.plm.pdm.iba.service.TyplmIBAAttributeService;
import com.hustcad.plm.pdm.iba.service.TyplmIBAValueService;
import com.hustcad.plm.rpm.model.converters.ActiveTreeDTOConverter;
import com.hustcad.plm.rpm.model.dto.active.PlusTaskDTO;
import com.hustcad.plm.rpm.model.dto.active.TyppmActiveTreeDTO;
import com.hustcad.plm.rpm.model.dto.admin.TyppmProjectDTO;
import com.hustcad.plm.rpm.model.dto.job.TyppmJobDTO;
import com.hustcad.plm.rpm.model.dto.plan.TyppmMileStoneDTO;
import com.hustcad.plm.rpm.model.entity.folder.SubFolder;
import com.hustcad.plm.rpm.model.entity.plan.TyppmPlan;
import com.hustcad.plm.rpm.model.vo.admin.ProjectVO;
import com.hustcad.plm.rpm.model.vo.change.PlanChangeInfoVO;
import com.hustcad.plm.rpm.project.service.TyppmProjectService;
import com.hustcad.plm.rpm.service.plan.TyppmPlanActiveService;
import com.hustcad.plm.rpm.util.request.RequestBase;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.dto.constraint.IbaDTO;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import com.ty.basic.vo.AttributeVO;
import com.ty.ppm.api.service.admin.ProjectService;
import com.ty.ppm.api.service.plan.PlanService;
import com.ty.ppm.model.constant.ProjectMngConstant;
import com.ty.ppm.model.dto.active.ActiveTreeDTO;
import com.ty.ppm.model.dto.plan.PlanActivePublishDTO;
import com.ty.ppm.model.entity.admin.Project;
import com.ty.ppm.model.entity.plan.Plan;
import com.ty.ppm.model.entity.plan.PlanActive;
import com.ty.ppm.model.utils.Tools;
import com.ty.ppm.service.service.impl.plan.PlanActiveOperateServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.cqrt.util.WorkdayCalculator.calculateWorkdayDuration;

@Aspect
@Component
@Slf4j
public class ProjectAop {

    @Resource
    private RTProjectMapper rtProjectMapper;
    @Resource
    private TyppmPlanActiveService typpmPlanActiveService;
    @Resource
    private PlanActiveOperateServiceImpl planActiveOperateService;
    @Resource
    private PlanService planService;
    @Resource
    private ProjectService projectService;
    @Resource
    private BaseLinePlanExpandMapper baseLinePlanExpandMapper;
    @Resource
    private TyplmAttributeValueService typlmAttributeValueService;
    @Resource
    private RTTaskMapper rtTaskMapper;
    @Resource
    private ProjectCodeGenerator projectCodeGenerator;
    @Value("${rt.plan.state}")
    private String enumOID;
    @Resource
    private RTProjectsTemplateMapper rtProjectsTemplateMapper;
    @Resource
    private RTOutRuleMapper rtOutRuleMapper;
    @Resource
    private ProjectTemplateLinkMapper projectTemplateLinkMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private TyppmProjectService typpmProjectService;
    @Resource
    private RTProjectTemplateService projectTemplateService;

    @Resource
    private TyplmCommonAttributeService typlmCommonAttributeService;

    @Resource
    private RTProjectKnowledgeLinkMapper rtProjectKnowledgeLinkMapper;

    @Before("execution(* com.ty.ppm.service.service.impl.plan.PlanActiveOperateServiceImpl.publichPlanCheck(..))")
    public void checkPlanPush(JoinPoint pjp) throws Throwable {
        IdentifierEntity identifierEntity = (IdentifierEntity) pjp.getArgs()[0];
        PlanActive planActive = planActiveOperateService.selectOneByOID(identifierEntity.getOid());
        if (ObjectUtil.isNull(planActive)) {
            return;
        }
        Plan plan = planService.selectOneByOID(planActive.getRootOID());
        Project project = this.projectService.selectOneByOID(plan.getParentOID());
        if (!Long.valueOf((long) ProjectMngConstant.PROJECT_STATE_NOT_STARTED).equals(project.getCompletionstatus())) {
            throw SystemErrorCodeEnum.BAN_PUBLISHED.getException(new Object[0]);
        }
    }

    @Before("execution(* com.ty.ppm.service.service.impl.plan.PlanActiveOperateServiceImpl.publish(..))")
    public void checkPlanPushPlus(JoinPoint pjp) throws Throwable {
        PlanActivePublishDTO publishDTO = (PlanActivePublishDTO) pjp.getArgs()[0];
        PlanActive planActive = planActiveOperateService.selectOneByOID(publishDTO.getOid());
        if (ObjectUtil.isNull(planActive)) {
            return;
        }
        Plan plan = planService.selectOneByOID(planActive.getRootOID());
        Project project = this.projectService.selectOneByOID(plan.getParentOID());
        if (!Long.valueOf((long) ProjectMngConstant.PROJECT_STATE_NOT_STARTED).equals(project.getCompletionstatus())) {
            throw SystemErrorCodeEnum.BAN_PUBLISHED.getException(new Object[0]);
        }
    }

    @Before("execution(* com.hustcad.plm.rpm.service.plan.TyppmPlanService.publishPlan(..))")
    public void beforePlanPush(JoinPoint joinPoint) throws Throwable {
        PlanChangeInfoVO params= (PlanChangeInfoVO) joinPoint.getArgs()[0];
        //1.判断计划是否都有执行人
        Map<String, Object> param = new HashMap();
        List<PlusTaskDTO> plusTaskDTOS = typpmPlanActiveService.queryPlanActiveTreeByPlanOidAndOtype(
                params.getPlanoid(), TableTypeConstrant.TY_PLAN_OTYPE, param);

        //子集合里面也要检查
        for (PlusTaskDTO taskDTO : plusTaskDTOS) {
            // 检查executorOID是否为null
            checkExecutorOID(taskDTO);
        }

        //2.判断项目是否为启动
        String state = rtTaskMapper.setIsState(params.getProjectoid(), RTPlmConstant.EXECUTIONSTATUS);
        if (StringUtils.equals(state, "未启动") || StringUtils.equals(state, "编制中") ) {
           return;
        }
//
//        if (StringUtils.equals(state, "正常") ) {
//            throw RTErrorCodeEnum.PLAN_PUBLISH_START_ERROR.getException("当前项目为启动状态,不允许发布");
//        }
    }

    // 递归检查方法：检查当前任务及其所有子任务
    private void checkExecutorOID(PlusTaskDTO taskDTO) {
        // 1. 检查当前任务的executorOID
        if (ObjectUtil.isNull(taskDTO.getExecutorOID())) {
            // 可以补充任务ID等信息，方便定位问题
            throw RTErrorCodeEnum.EXECUTOR_NOT_EXIST.getException("当前计划存在执行人为空");
        }

        // 2. 检查子任务（如果有子任务）
        List<PlusTaskDTO> children = taskDTO.getChildren();
        if (CollectionUtil.isNotEmpty(children)) {
            for (PlusTaskDTO childTask : children) {
                // 递归检查子任务
                checkExecutorOID(childTask);
            }
        }
    }

    @Pointcut("execution(* com.hustcad.plm.rpm.service.impl.plan.TyppmPlanActiveServiceImpl.setAdvancedSearchProjectMileStone(..))")
    public void milestoneSettingPointcut() {}


    @After("milestoneSettingPointcut()&& args(list)")
    public void afterMilestoneSet(JoinPoint joinPoint, List<ProjectEntityVO> list) {
        try {
            if (CollectionUtil.isEmpty(list)) {
                return;
            }
            for (ProjectEntityVO projectVO : list) {
                if (StringUtils.isEmpty(projectVO.getCurMileStoneOid())) {
                    continue;
                }
                LocalDateTime actualFinishDate = getActualMilestoneFinishDate(projectVO.getCurMileStoneOid());
                if (ObjectUtil.isNull(actualFinishDate)) {
                    continue;
                }
                BigInteger projectId = projectVO.getOid();
                // 获取项目的所有里程碑并排序
                List<TyppmMileStoneDTO> mileStoneList = typpmPlanActiveService.getMileStoneByProjectOids(
                        Collections.singletonList(projectId.toString()));
                if (CollectionUtil.isEmpty(mileStoneList)) {
                    continue;
                }
                List<TyppmMileStoneDTO> sortedMileStones = getSortedMileStones(mileStoneList);
                boolean allExpired = true;
                for (TyppmMileStoneDTO ms : sortedMileStones) {
                    LocalDateTime finishDate = getActualMilestoneFinishDate(ms.getOid());
                    if (finishDate != null && !finishDate.toLocalDate().isBefore(LocalDate.now())) {
                        projectVO.setCurMileStoneOid(ms.getOid());
                        projectVO.setCurMileStoneName(ms.getName());
                        projectVO.setFinish(finishDate);
                        allExpired = false;
                        break;
                    }
                }
                // 如果所有里程碑都已过期，标记项目为完成
                if (allExpired) {
                    markProjectAsCompleted(projectVO);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private LocalDateTime getActualMilestoneFinishDate(String milestoneOid) {
        try {
            return rtProjectMapper.selectFinishById(Tools.toBigInteger(milestoneOid));
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    private List<TyppmMileStoneDTO> getSortedMileStones(List<TyppmMileStoneDTO> mileStoneList) {
        return mileStoneList.stream()
                .sorted(Comparator.comparing(ms -> getActualMilestoneFinishDate(ms.getOid())))
                .collect(Collectors.toList());
    }

    // 标记项目为全部完成
    private void markProjectAsCompleted(ProjectEntityVO projectVO) {
        projectVO.setCurMileStoneOid(null);
        projectVO.setCurMileStoneName(null);
        projectVO.setFinish(null);
        projectVO.setProjectCompleted(true);
    }


    //    @Around("execution(* com.hustcad.plm.rpm.service.impl.job.TyppmJobServiceImpl.setSubmitState(..))")
    //    public Object checkSubmitJobBefore(ProceedingJoinPoint pjp) {
    //        JobStatusUpdateDTO job = (JobStatusUpdateDTO) pjp.getArgs()[0];
    //        if (!existSalveJob(job.getJobId())) {
    //            throw RTErrorCodeEnum.RELATIONJOB_NOT_COMPLETE.getException("关联项目的任务未完成,无法提交.");
    //        } else {
    //            try {
    //                Object obj = pjp.proceed();
    //                return obj;
    //            } catch (Throwable e) {
    //                throw RTErrorCodeEnum.JOB_SUBMIT_FAILED.getException("任务提交异常");
    //            }
    //        }
    //    }
    //
    //    private boolean existSalveJob(String jobId) {
    //        return rtProjectMapper.existSalveJob(jobId);
    //    }


    //@Before("execution(* com.hustcad.plm.rpm.service.change.TyppmChangeInfoService.createPlanChangeInfo(..))")
//    public void checkSubmitJobBefore(JoinPoint joinPoint) {
//        PlanChangeInfoVO planChangeInfoVO = (PlanChangeInfoVO) joinPoint.getArgs()[0];
//        //根据项目的OID批量修改项目的iba
//        planChangeInfoVO.getProjectoid();
//
//    }

    @Before("execution(* com.hustcad.plm.pdm.iba.service.TyplmAttributeValueService.getAttrValueTableByEntitys(*,*))")
    public void beforePopulateIba(JoinPoint joinPoint) {
        if (!StringUtils.equals(joinPoint.getArgs()[1].toString(), TableTypeConstrant.TY_JOB_OTYPE)) {
            return;
        }
        //新增扩展属性
        List<BigInteger> oIds = (List<BigInteger>) joinPoint.getArgs()[0];
        if (CollUtil.isEmpty(oIds)) {
            return;
        }
        Map<String, List<AttributeVO>> ibaMaps = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                oIds,
                TableTypeConstrant.TY_JOB_OTYPE,
                Collections.singletonList("ExecutionStatus"));
        // 2. 筛选出ExecutionStatus值为空的计划OID
        List<BigInteger> emptyStatusOids = new ArrayList<>();
        for (BigInteger oid : oIds) {
            String oidStr = oid.toString();
            List<AttributeVO> attrs = ibaMaps.get(oidStr);
            // 标记是否需要更新
            boolean needUpdate = false;
            if (CollectionUtil.isEmpty(attrs)) {
                // 情况1：无此属性
                needUpdate = true;
            } else {
                // 情况2：有属性但值为空（String类型专用判断）
                AttributeVO attr = attrs.get(0);
                String value = attr.getAttributeValue();
                // 空值判断：null或空白字符串（包括纯空格）
                needUpdate = StringUtils.isBlank(value);
            }
            if (needUpdate) {
                emptyStatusOids.add(oid);
            }
        }

        // 3. 没有需要更新的计划，直接返回
        if (emptyStatusOids.isEmpty()) {
            return;
        }

        // 4. 为需要更新的计划创建IBA属性（设置为"编制中"）
        List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();
        for (BigInteger oid : emptyStatusOids) {
            CTyEntityBaseDO entityBase = new CTyEntityBaseDO(oid, TableTypeConstrant.TY_JOB_OTYPE);
            IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "编制中");
            SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
            objWithIbaList.add(saveObjDto);
        }

        // 5. 批量保存更新
        typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);


    }

    // 创建IBA DTO (复用原有逻辑)
    private IbaDTO createIbaDto(String attrKey, String attrValue) {
        IbaDTO ibaDTO = new IbaDTO();
        ibaDTO.setKey(attrKey);
        ibaDTO.setValue(attrValue);
        return ibaDTO;
    }

    // 创建保存对象的DTO (复用原有逻辑)
    private SaveObjIBADTO createSaveObjDto(CTyEntityBaseDO entityBase, IbaDTO ibaDTO) {
        SaveObjIBADTO saveObjDto = new SaveObjIBADTO();
        saveObjDto.setCTyEntityBaseDO(entityBase);
        saveObjDto.setObjIbaList(Collections.singletonList(ibaDTO));
        return saveObjDto;
    }


    @Around("execution(* com.hustcad.plm.rpm.service.forpdm.admin.ProjectServiceForPdm.insertProject(..))")
    public Object afterPopulateProjectIba(ProceedingJoinPoint pjp) throws Throwable {

        Object[] args = pjp.getArgs();
        TyppmProjectDTO projectDTO = (TyppmProjectDTO) args[0];
        Map<String, List<String>> ibaAttribute = projectDTO.getIbaAttribute();


        List<String> devCode = projectDTO.getIbaAttribute().get("ProjectDevelopmentOrder");
        List<BigInteger> devOidList = rtProjectMapper.selectDevIfExist(devCode.get(0));
        if(CollUtil.isEmpty(ibaAttribute.get("IsYearImport"))) {
            if (!CollUtil.isEmpty(devOidList)) {
                throw RTErrorCodeEnum.CHECK_ORDER_ERROR.getException("开发令已存在项目");
            }
        }
        projectDTO.setProjectNumber(projectCodeGenerator.generateProjectCode());
        projectDTO.setProjectManagerList(new ArrayList<>());
        projectDTO.setProjectManager(new ArrayList<>());
        //获取负责人
        UserDO userDO = rtProjectMapper.selectUserDetailByCode(devCode.get(0));
        if(CollUtil.isEmpty(ibaAttribute.get("IsYearImport"))) {
            if (!userDO.getFullname().equals(TyAccountContext.getUser().getFullname())) {
                throw RTErrorCodeEnum.CREATE_PJ_ERROR.getException("您不是该项目的开发令负责人，不能创建该项目");
            }
        }
            if(Objects.isNull(userDO)){
                return pjp.proceed();
            }


        //获取开发令信息
        Map<String, String> stringStringMap = rtProjectMapper.selectDevelopmentOrderByOrderName(devCode.get(0));
        Map<String, Object> pmMap = new HashMap<>();

        List<TyppmUser> projectManagerList = new ArrayList<>();
        TyppmUser typpmUser = new TyppmUser();
        if (ObjectUtil.isNotNull(userDO)) {
            typpmUser.setOid(userDO.getOid().toString());
            typpmUser.setDescription(userDO.getDescription());
            typpmUser.setName(userDO.getName());
            typpmUser.setOtype(userDO.getOtype());
            projectManagerList.add(typpmUser);
        }

        if (CollUtil.isEmpty(projectDTO.getProjectManagerList())) {
            projectDTO.setProjectManagerList(projectManagerList);
        }
        if (CollUtil.isEmpty(projectDTO.getIbaAttribute().get("CreationMethod"))) {
            ibaAttribute.put("CreationMethod", Collections.singletonList("Reference"));

        }

        args[0] = projectDTO;
        Object proceed = pjp.proceed(args);
        TyppmProjectDTO typpmProjectDTO = (TyppmProjectDTO) proceed;
        String projectOid = typpmProjectDTO.getOid().toString();
        //新增扩展属性
        // 3. 准备批量添加IBA属性
        List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();
        // 4. 为每个OID创建IBA属性
        CTyEntityBaseDO entityBase = new CTyEntityBaseDO(Tools.toBigInteger(projectDTO.getOid()),
                                                         TableTypeConstrant.TY_PROJECT_TYPE);
        IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "编制中");
        SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
        objWithIbaList.add(saveObjDto);


        // 5. 批量保存IBA属性
        if (CollUtil.isNotEmpty(objWithIbaList)) {
            typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
        }

        UserDO user = TyAccountContext.getUser();

        if(!user.getFullname().equals(userDO.getFullname())){
            Map<String, Object> pMap = new HashMap<>();
            pMap.put("projectOid",projectOid);
            pMap.put("roleName","PROJECT DIRECTOR");
            pMap.put("userOid",user.getOid().toString());
            typpmProjectService.deleteProjectManagerOrAdministrator(pMap);

        }
        pmMap.put("projectOid",projectOid);
        pmMap.put("roleName","PROJECT DIRECTOR");
        pmMap.put("userOid","105");
        typpmProjectService.deleteProjectManagerOrAdministrator(pmMap);
        Map<String, Object> ppMap = new HashMap<>();
        ppMap.put("projectOid",projectOid);
        ppMap.put("roleName","PROJECT MANAGER");
        ppMap.put("userOid",user.getOid().toString());
        typpmProjectService.deleteProjectManagerOrAdministrator(ppMap);
        String planTemplateOID = projectDTO.getPlanTemplateOID();
        if (StringUtils.isNotBlank(planTemplateOID)) {
            List<RTKnowTempDocDO> rtKnowTempDocDOS = rtProjectKnowledgeLinkMapper.selectKnowTempDoc(new BigInteger(planTemplateOID));
            for (RTKnowTempDocDO rtKnowTempDocDO : rtKnowTempDocDOS){
                rtKnowTempDocDO.setProjectId(new BigInteger(projectOid));
                rtKnowTempDocDO.setPlanOid(new BigInteger(typpmProjectDTO.getPlan().getOid()));
                BigInteger oid = snowflakeIdComponent.getInstance().nextId();
                rtKnowTempDocDO.setOid(oid);
                rtProjectKnowledgeLinkMapper.insertKnowTempDoc(rtKnowTempDocDO);
            }
        }
        return proceed;

    }

//增加的PMO权限
    @Around("execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.doInsertProjectManagerOrAdministrator(..))")
    public Object insertProjectManager(ProceedingJoinPoint pjp) throws Throwable {
        Map<String, Object> preValueMap = (Map<String, Object>) pjp.getArgs()[0];
        String projectid = (String) preValueMap.get("projectOid");
        //Map<String, Object> stringObjectMap = rtProjectMapper.selectProjectByOid(projectid);
        List<BigInteger> bigIntegers = rtTaskMapper.selectJobIdByProjectId(new BigInteger(projectid));
        if (CollUtil.isEmpty(bigIntegers)){
            return pjp.proceed();
        }

        BigInteger pmo=rtProjectMapper.selectPMO("PMO");
           // BigInteger aOid=new BigInteger("754161145811582976");
        String userOId = TyAccountContext.getUser().getOid().toString();
        BigInteger bOid=new BigInteger(userOId);
            List<BigInteger>  permission=rtProjectMapper.selectPermission(pmo,bOid);
            if (CollUtil.isEmpty(permission)) {
                throw RTErrorCodeEnum.PROJECT_PERMISSON_ERROR.message("不是PMO用户，无操作权限");
            }


        String isImport ="";
        if (preValueMap.get("是不是搁这导入人呢？")!=null){
            isImport=preValueMap.get("是不是搁这导入人呢？").toString();
        }

        BigInteger projectOid = new BigInteger(preValueMap.get("projectOid").toString());
        String projectType="ty.inteplm.project.CTyProject";
        String userOid = preValueMap.get("userOid").toString();
        Timestamp createTime = Timestamp.valueOf(LocalDateTime.now());
        List<BigInteger> domainOidList = rtProjectMapper.selectDomainByProjectOID(projectOid);
        BigInteger domainOid =null;
        if (domainOidList.size()>0){
            domainOid = domainOidList.get(0);
        }


        String domainOType = "ty.inteplm.domain.CTyDomain";
        String roleName = preValueMap.get("roleName").toString();
        List<BigInteger> oidList = rtProjectMapper.selectOidByMemberLink(userOid);

        BigInteger oid =null;
        if (oidList.size()>0){
            oid = oidList.get(0);
        }

        String oType = "ty.inteplm.org.CTyGroup";
        if (projectOid!=null&&domainOid!=null&&oid!=null&&roleName!=null&&isImport.equals("Yes")) {
            rtProjectMapper.insertGroup(projectOid, projectType, createTime, domainOid, domainOType, roleName, oid, oType);
        }
        return pjp.proceed();
    }
    //删除项目经理权限
    @Around("execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.deleteProjectManagerOrAdministrator(..))")
    public Object deleteProjectManager(ProceedingJoinPoint pjp) throws Throwable {
        Map<String, Object> preValueMap = (Map<String, Object>) pjp.getArgs()[0];
        String projectOid = (String) preValueMap.get("projectOid");
       // Map<String, Object> stringObjectMap = rtProjectMapper.selectProjectByOid(projectOid);
        List<BigInteger> bigIntegers = rtTaskMapper.selectJobIdByProjectId(new BigInteger(projectOid));
        if (CollUtil.isEmpty(bigIntegers)){
            return pjp.proceed();
        }
        BigInteger pmo=rtProjectMapper.selectPMO("PMO");
        //BigInteger aOid = new BigInteger("754161145811582976");
        String oid = TyAccountContext.getUser().getOid().toString();
        BigInteger bOid = new BigInteger(oid);
        List<BigInteger> permission = rtProjectMapper.selectPermission(pmo, bOid);
        if (CollUtil.isEmpty(permission)) {
            throw RTErrorCodeEnum.PROJECT_PERMISSON_ERROR.message("不是PMO用户，无操作权限");
        }
        return pjp.proceed();
    }



    //查看团队，并增加
    @Around("execution(* com.hustcad.plm.rpm.service.team.TyppmProjectTeamService.queryContainerTeamByContainer(..))")
    public Object insertOrderValue(ProceedingJoinPoint pjp) throws Throwable {
        // 项目Oid
        String containerOid=(String) pjp.getArgs()[0];
        String name = rtProjectMapper.selectProjectNameByProjectOid(containerOid);
        // 判断是否已经存在计划模板
        List<BigInteger> plan = rtProjectMapper.selectplanTemplate(containerOid);
        if (CollUtil.isNotEmpty(plan)) {
            if (plan.get(0).equals(BigInteger.valueOf(2))) {
                return pjp.proceed();
            }
        }
        Map<String, String> stringStringMap = rtProjectMapper.selectDevelopmentOrderByProjectName(name);
        if (stringStringMap == null) {
            return pjp.proceed();
        }
        String responsiblePerson = stringStringMap.get("RESPONSIBLE_PERSON");
        if (StrUtil.isNotBlank(responsiblePerson)) {
            UserDO userDO = rtProjectMapper.selectUserByName(responsiblePerson);
            String userOid = userDO.getOid().toString();
            Map<String, Object> pmMap = new HashMap<>();
            pmMap.put("userOid", userOid);
            pmMap.put("projectOid", containerOid);
            pmMap.put("roleName", "PROJECT DIRECTOR");
            List<BigInteger> bigInteger = new ArrayList<>();
            if (StrUtil.isNotBlank(containerOid)) {
                BigInteger projectOid = new BigInteger(containerOid);
                if (StrUtil.isNotBlank(userOid)) {
                    BigInteger userId = new BigInteger(userOid);
                    bigInteger = rtProjectMapper.checkUser(projectOid, userId);
                }
            }
            if (bigInteger.size() == 0) {
                typpmProjectService.doInsertProjectManagerOrAdministrator(pmMap);
            }
        }
        return pjp.proceed();


    }

    @Around("execution(* com.hustcad.plm.rpm.service.remote.HandlerJavaPDM.getPreferenceValueMap(..))")
    public Object getPreValueMap(ProceedingJoinPoint pjp) throws Throwable {
        Map<String, Object> preValueMap = (Map<String, Object>) pjp.proceed();
        preValueMap.put("publishPlanActiveEnable", Boolean.FALSE);
        return preValueMap;
    }
//修改模板时，状态变成草稿
//    @Around("execution(* com.hustcad.plm.rpm.service.plan.TyppmGanttChartService.saveTableTreeEx(..))")
//    public Object checkTemplateIsChange(ProceedingJoinPoint pjp) throws Throwable {
//
//        String planOid  = (String)pjp.getArgs()[0];
//        BigInteger isTemplate = rtProjectsTemplateMapper.selectIsTemplate(new BigInteger(planOid));
//        if(isTemplate.equals(BigInteger.valueOf(2))) {
//            List<PlusTaskSaveDTO> data = (List<PlusTaskSaveDTO>) pjp.getArgs()[1];
//            Pattern PATTERN = Pattern.compile("-.+$");
//            if (!CollUtil.isEmpty(data)) {
//                String planName = rtProjectMapper.selectPlanNameByPlanOid(planOid);
//                String projectId = rtProjectMapper.selectProjectIdByPlanOid(planOid);
//
//                planName = PATTERN.matcher(planName).replaceAll("");
//                planName = planName + "-草稿";
//                rtProjectMapper.updatePlanName(planOid, planName);
//                projectTemplateService.updateTemplateStatus(projectId, "0");
//
//            }
//        }
//        return pjp.proceed();
//    }
//参考创建时，状态变成草稿
@Around("execution(* com.hustcad.plm.rpm.project.controller.ProjectController.saveAsTemplate(..))")
public Object templateSaveAsTemplate(ProceedingJoinPoint pjp) throws Throwable {

    Map<String, String> params = (Map<String, String>) pjp.getArgs()[0];

    String projectOID = (String) params.get("projectOID");
    String templateName = (String) params.get("templateName");
    if (projectOID != null && templateName != null) {
        Pattern PATTERN = Pattern.compile("-.+$");
        templateName = PATTERN.matcher(templateName).replaceAll("");
        templateName = templateName + "-草稿";
        BigInteger planOID = rtProjectMapper.selectPlanOIDByProjectOID(projectOID);
        String planOid = planOID.toString();
        params.put("templateName", templateName);
        rtProjectMapper.updatePlanName(planOid, templateName);
        projectTemplateService.updateTemplateStatus(projectOID, "0");
    }
    Object proceed = pjp.proceed();

    return proceed;
}

    @AfterReturning("execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.setProjectStateStarted(..))")
    public void afterSetProjectStateStarted(JoinPoint joinPoint) {

        List<String> list = (List<String>) joinPoint.getArgs()[0];

        List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();

        CTyEntityBaseDO projectBase = new CTyEntityBaseDO(Tools.toBigInteger(list.get(0)),
                                                          TableTypeConstrant.TY_PROJECT_TYPE);
        IbaDTO iba = createIbaDto("ExecutionStatus", "正常");
        SaveObjIBADTO saveObj = createSaveObjDto(projectBase, iba);
        objWithIbaList.add(saveObj);
        // 4. 为每个OID创建IBA属性
        List<BigInteger> jobId = rtProjectMapper.selectJobByOID(list.get(0));
        if (CollUtil.isEmpty(jobId)) {
            return;
        }
        for (BigInteger job : jobId) {
            CTyEntityBaseDO entityBase = new CTyEntityBaseDO(job,
                                                             TableTypeConstrant.TY_JOB_OTYPE);
            IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "正常");
            SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
            objWithIbaList.add(saveObjDto);
        }
        // 5. 批量保存IBA属性
        if (CollUtil.isNotEmpty(objWithIbaList)) {
            typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
        }

        //发布任务
        rtProjectMapper.updateJobPublish(jobId);
        //执行人
        for (BigInteger jobID : jobId) {
            rtProjectMapper.updateJobById(jobID);
        }


    }


    @AfterReturning("execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.setProjectStatePaused(..))")
    public void afterSetProjectStatePaused(JoinPoint joinPoint) {
        List<String> list = (List<String>) joinPoint.getArgs()[0];
        List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();

        // 4. 为每个OID创建IBA属性
        CTyEntityBaseDO entityBase = new CTyEntityBaseDO(Tools.toBigInteger(list.get(0)),
                                                         TableTypeConstrant.TY_PROJECT_TYPE);
        IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "暂停");
        SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
        objWithIbaList.add(saveObjDto);
        List<BigInteger> jobId = rtProjectMapper.selectJobByOID(list.get(0));
        if (CollUtil.isEmpty(jobId)) {
            return;
        }
        for (BigInteger job : jobId) {

             CTyEntityBaseDO jobBase = new CTyEntityBaseDO(job,
                                                              TableTypeConstrant.TY_JOB_OTYPE);
             IbaDTO iba = createIbaDto("ExecutionStatus", "暂停");
             SaveObjIBADTO saveObj = createSaveObjDto(jobBase, iba);
             objWithIbaList.add(saveObj);

        }

        // 5. 批量保存IBA属性
        if (CollUtil.isNotEmpty(objWithIbaList)) {
            typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
        }

    }


   // @Around("execution(* com.hustcad.plm.rpm.service.plan.TyppmPlanActiveService.queryPlanActiveTreeByRootOIDAndRootOTYPE(..))")
//    public Object afterSetProjectState(ProceedingJoinPoint pjp) throws Throwable {
//        List<ActiveTreeDTO> treeDTOList = (List<ActiveTreeDTO>) pjp.proceed();
//        for (ActiveTreeDTO treeDTO : treeDTOList){
//            Long actualDuration = getActualDuration(treeDTO);
//            if (treeDTO.getIbaAttribute()==null) {
//                treeDTO.setIbaAttribute(new HashMap<>());
//            }
//            if (actualDuration!=0l) {
//                treeDTO.getIbaAttribute().put("ActualDuration", Collections.singletonList(actualDuration.toString()));
//            }
//            List<ActiveTreeDTO> children = treeDTO.getChildren();
//            if (CollUtil.isNotEmpty(children)){
//                for (ActiveTreeDTO child : children){
//                    if (child.getIbaAttribute()==null) {
//                        child.setIbaAttribute(new HashMap<>());
//                    }
//                    Long actualChildDuration = getActualDuration(child);
//                    if (actualChildDuration!=0l) {
//                        child.getIbaAttribute().put("ActualDuration", Collections.singletonList(actualChildDuration.toString()));
//                    }
//                }
//            }
//        }


//        return pjp.proceed();
//    }
public Long getActualDuration(ActiveTreeDTO treeDTO) {
    Long actualDuration = 0l;
    if (treeDTO != null) {
        //获取计划完成百分比
        if (treeDTO.getPercentWorkComplete() != null) {
            Double percentWorkComplete = treeDTO.getPercentWorkComplete();

            if (treeDTO.getDuration() != null && treeDTO.getFinishDate() != null && treeDTO.getStartDate() != null) {
                // 方法1：使用系统默认时区
                LocalDateTime startDate = treeDTO.getStartDate().toInstant().atZone(ZoneId.systemDefault())
                        .toLocalDateTime();
                LocalDateTime finishDate = treeDTO.getFinishDate().toInstant().atZone(ZoneId.systemDefault())
                        .toLocalDateTime();
                //获得工期
                long duration = calculateWorkdayDuration(startDate, finishDate);
                actualDuration = (long) (duration * percentWorkComplete);
            }
            //实际完成工期
        }
    }
    return actualDuration;
}


    /*    List<ActiveTreeDTO> treeDTOList = (List<ActiveTreeDTO>) pjp.proceed();
        List<TyppmActiveTreeDTO> activeTreeDTOS = activeTreeDTOConverter.transList(treeDTOList);
        activeTreeDTOS.forEach((treeDTO) -> {
            if (com.hustcad.plm.rpm.constant.ProjectMngConstant.ACTIVE_STATUS_COMPLETED_OVERDUE.equals(
                    treeDTO.getExecutedStatus()) || com.hustcad.plm.rpm.constant.ProjectMngConstant.ACTIVE_STATUS_OVERDUE.equals(
                    treeDTO.getExecutedStatus()) || com.hustcad.plm.rpm.constant.ProjectMngConstant.ACTIVE_STATUS_COMPLETED.equals(
                    treeDTO.getExecutedStatus()) || com.hustcad.plm.rpm.constant.ProjectMngConstant.ACTIVE_STATUS_NORMAL.equals(
                    treeDTO.getExecutedStatus())) {
                this.checkActiveExecutedStatus(treeDTO);
            }
        });
        return BeanUtil.copyToList(activeTreeDTOS, ActiveTreeDTO.class);
    }


    private void checkActiveExecutedStatus(TyppmActiveTreeDTO activeTreeDTO) {
        LocalDateTime finishDate = activeTreeDTO.getFinishDate();
        LocalDateTime actualFinishDateTime = activeTreeDTO.getActualFinishDate();


        if (com.hustcad.plm.rpm.constant.ProjectMngConstant.ACTIVE_STATUS_NORMAL.equals(
                activeTreeDTO.getExecutedStatus()) || com.hustcad.plm.rpm.constant.ProjectMngConstant.ACTIVE_STATUS_OVERDUE.equals(
                activeTreeDTO.getExecutedStatus())) {
            this.updateExecutedStatus(activeTreeDTO, finishDate, actualFinishDateTime);
        }
    }

    private void updateExecutedStatus(TyppmActiveTreeDTO dto, LocalDateTime finishDate,
                                      LocalDateTime actualFinishDateTime) {
            LocalDate planFinishDate;
        if (actualFinishDateTime == null && finishDate != null) {
            planFinishDate = finishDate.toLocalDate();
            Map<String, List<com.ty.basic.vo.AttributeVO>> ibaMaps = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                    Collections.singletonList(Tools.toBigInteger(dto.getJobOID())),
                    TableTypeConstrant.TY_JOB_OTYPE,
                    Collections.singletonList("KeyNode"));

            boolean isKeyTask = ibaMaps.values().stream()
                    .flatMap(List::stream)
                    .map(AttributeVO::getAttributeValue)
                    .anyMatch(attrValue -> StringUtils.isNotEmpty(String.valueOf(attrValue)));


            if (planFinishDate.isBefore(LocalDate.now())) {
                //关键任务延期
                if (isKeyTask) {
                    //查看所在的阶段任务
                    String language = CommonConstant.GET_LOCALE_PROPERTY_VALUE_LANGUAGE.get(
                            TyCommonExtUtil.getFrontLanguage());
                    List<EnumerationItemHandleVO> enumerationItemHandleVOS = this.typlmEnumerationItemMapper.queryEnumByDefOid(
                            new BigInteger(enumOID), language);
                    Map<String, Integer> delayDaysMap = getDelayDays(enumerationItemHandleVOS);

                    // 获取预延期和延期的天数配置
                    int preDelayDays = delayDaysMap.getOrDefault("预延期", 15);
                    int delayDays = delayDaysMap.getOrDefault("延期", 30);

                    if (preDelayDays > delayDays) {
                        throw RTErrorCodeEnum.DAY_NOT_VALID.getException("预延期天数大于延期天数,请重新设置");
                    }

                    // 计算关键任务实际延期天数（当前时间 - 计划完成时间）
                    long actualDelayDays = ChronoUnit.DAYS.between(planFinishDate, LocalDate.now());
                    //获取阶段任务
                    BigInteger stageJobOID = rtProjectMapper.selectStageById(dto.getJobOID());
                    Job stageJob = rtProjectMapper.selectStageJob(stageJobOID);
                    Date finishdate = stageJob.getFinishdate();

                    if (stageJob.getActualfinishdate() == null && finishdate != null && finishdate.toInstant().isBefore(
                            Instant.now())) {
                        updateStageAndProjectStatus(stageJobOID, Tools.toBigInteger(dto.getContainerOID()), "延期");
                    } else if (actualDelayDays > preDelayDays && actualDelayDays <= delayDays) {
                        //超过设置的预延期时间
                        updateStageAndProjectStatus(stageJobOID, Tools.toBigInteger(dto.getContainerOID()), "预延期");
                    } else if (actualDelayDays > delayDays) {
                        //超过设置的延期时间
                        updateStageAndProjectStatus(stageJobOID, Tools.toBigInteger(dto.getContainerOID()), "延期");
                    } else {
                        //未超过设置的预延期时间
                        updateStageAndProjectStatus(stageJobOID, Tools.toBigInteger(dto.getContainerOID()), "正常");
                    }
                } else if (ObjectUtil.equals(dto.getOutLineLevel(), 1)) {
                    updateStageAndProjectStatus(Tools.toBigInteger(dto.getJobOID()),
                                                Tools.toBigInteger(dto.getContainerOID()), "延期");
                } else {
                    List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();
                    CTyEntityBaseDO entityBase = new CTyEntityBaseDO(Tools.toBigInteger(dto.getJobOID()),
                                                                     TableTypeConstrant.TY_JOB_OTYPE);
                    IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "延期");
                    SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
                    objWithIbaList.add(saveObjDto);
                    // 批量保存IBA属性
                    if (CollUtil.isNotEmpty(objWithIbaList)) {
                        typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
                    }
                }
            } else {
                List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();
                CTyEntityBaseDO entityBase = new CTyEntityBaseDO(Tools.toBigInteger(dto.getJobOID()),
                                                                 TableTypeConstrant.TY_JOB_OTYPE);
                IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "正常");
                SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
                objWithIbaList.add(saveObjDto);
                // 批量保存IBA属性
                if (CollUtil.isNotEmpty(objWithIbaList)) {
                    typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
                }
            }
        } else if (actualFinishDateTime != null && finishDate != null) {
            planFinishDate = finishDate.toLocalDate();
            LocalDate actualFinishDate = actualFinishDateTime.toLocalDate();
            if (planFinishDate.isBefore(actualFinishDate)) {
                List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();
                CTyEntityBaseDO entityBase = new CTyEntityBaseDO(Tools.toBigInteger(dto.getJobOID()),
                                                                 TableTypeConstrant.TY_JOB_OTYPE);
                IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "延期完成");
                SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
                objWithIbaList.add(saveObjDto);
                // 批量保存IBA属性
                if (CollUtil.isNotEmpty(objWithIbaList)) {
                    typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
                }
            } else {
                List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();
                CTyEntityBaseDO entityBase = new CTyEntityBaseDO(Tools.toBigInteger(dto.getJobOID()),
                                                                 TableTypeConstrant.TY_JOB_OTYPE);
                IbaDTO ibaDTO = createIbaDto("ExecutionStatus", "完成");
                SaveObjIBADTO saveObjDto = createSaveObjDto(entityBase, ibaDTO);
                objWithIbaList.add(saveObjDto);
                // 批量保存IBA属性
                if (CollUtil.isNotEmpty(objWithIbaList)) {
                    typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
                }
            }
        }
    }
*/


    /**
     * 筛选显示名为"延期"和"预延期"的枚举项，并提取对应的天数（DESCRIPTION字段）
     *
     * @param enumerationItems 枚举项集合
     * @return 键为显示名（延期/预延期），值为对应天数的Map
     */
    private Map<String, Integer> getDelayDays(List<EnumerationItemHandleVO> enumerationItems) {
        // 校验入参
        if (enumerationItems == null || enumerationItems.isEmpty()) {
            return Collections.emptyMap();
        }

        // 目标显示名
        Set<String> targetNames = new HashSet<>(Arrays.asList("延期", "预延期"));

        return enumerationItems.stream()
                // 筛选目标显示名
                .filter(vo -> vo != null
                        && targetNames.contains(vo.getDisplayName()))
                // 转换为显示名-天数映射
                .collect(Collectors.toMap(
                        EnumerationItemHandleVO::getDisplayName,
                        vo -> parseDays(vo.getDescription()),
                        (existing, replacement) -> replacement // 处理重复项，保留最新
                ));
    }

    /**
     * 从描述中解析天数（处理空值和非数字格式）
     */
    private  int parseDays(String description) {
        if (description == null || description.trim().isEmpty()) {
            return 0;
        }
        // 提取数字（支持纯数字或包含文字的格式，如"3天"、"延期7天"）
        try {
            return Integer.parseInt(description.replaceAll("[^0-9]", ""));
        } catch (NumberFormatException e) {
            return 0; // 解析失败返回默认值
        }
    }


    /**
     * 统一更新阶段任务和项目状态
     */
    private void updateStageAndProjectStatus(BigInteger stageOID, BigInteger projectOID, String status) {
        List<SaveObjIBADTO> updateList = new ArrayList<>();
        // 更新阶段任务状态
        CTyEntityBaseDO stageEntity = new CTyEntityBaseDO(stageOID, TableTypeConstrant.TY_JOB_OTYPE);
        updateList.add(createSaveObjDto(stageEntity, createIbaDto("ExecutionStatus", status)));
        // 更新项目状态（与阶段状态一致）
        CTyEntityBaseDO projectEntity = new CTyEntityBaseDO(projectOID, TableTypeConstrant.TY_PROJECT_TYPE);
        updateList.add(createSaveObjDto(projectEntity, createIbaDto("ExecutionStatus", status)));
        // 批量保存
        if (CollUtil.isNotEmpty(updateList)) {
            typlmAttributeValueService.batchSaveIBAByObjList(updateList, false);
            log.info("已更新阶段任务[{}]和项目[{}]状态为：{}", stageOID, projectOID, status);
        }
    }

    //修改项目库字段值
    //@Around("execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.queryProjectAdvancedSearch(..)))")
//    public PageInfo<ProjectEntityVO> updateProjectLibraryAOP(ProceedingJoinPoint joinPoint) throws Throwable {
//        PageInfo<ProjectEntityVO> proceeds = (PageInfo<ProjectEntityVO>) joinPoint.proceed();
//        List<ProjectEntityVO> projectEntityVOList = proceeds.getList();
//        Map<BigInteger, ProjectEntityVO> projectmap = projectEntityVOList.stream().collect(Collectors.toMap(ProjectEntityVO::getOid, item -> item));
//        List<BigInteger> projectOidList = proceeds.getList().stream().map(ProjectEntityVO::getOid).collect(Collectors.toList());
//        List<TyppmPlan> planList = baseLinePlanExpandMapper.selectPlanByContainerOid(projectOidList);
//        Map<String,TyppmActiveTreeDTO> activeTreeDTOMap = new HashMap<>();
//        LocalDateTime now = LocalDateTime.now();
//        for (TyppmPlan typpmPlan : planList) {
//            Map<String, Object> params = new HashMap<>();
//            params.put("rootOID", typpmPlan.getOid());
//            params.put("rootOTYPE", TableTypeConstrant.TY_PJ_PLAN_OTYPE);
//            params.put("markfordelete", 0L);
//            List<TyppmActiveTreeDTO> firstPlan = this.typpmPlanActiveService.getLevelOnePlanActiveTreeByPlan(params);
//            Optional<TyppmActiveTreeDTO> matchingDTO = firstPlan.stream()
//                    .filter(dto -> {
//                        LocalDateTime start = dto.getEarlyStart();
//                        LocalDateTime finish = dto.getEarlyFinish();
//                        return start != null && finish != null &&
//                                start.isBefore(now) && finish.isAfter(now);
//                    })
//                    .findFirst();
//            matchingDTO.ifPresent(result -> activeTreeDTOMap.put(typpmPlan.getContainerOID(), result));
//        }
//        List<BigInteger> nowPlanStageOid = activeTreeDTOMap.values().stream().map(TyppmActiveTreeDTO::getOid).filter(Objects::nonNull).map(BigInteger::new).collect(Collectors.toList());
//        List<String> attrNameList = Arrays.asList("PersonCharge","RecoveryPlan","PostponedClassification","ReasonFor");
//        Map<String, List<AttributeVO>> ibaValueMap = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(nowPlanStageOid, TableTypeConstrant.TY_JOB_OTYPE, attrNameList);
//        for (String oid : activeTreeDTOMap.keySet()){
//            TyppmActiveTreeDTO typpmActiveTreeDTO = activeTreeDTOMap.get(oid);
//            List<AttributeVO> attributeVOS = ibaValueMap.get(typpmActiveTreeDTO.getOid());
//            ProjectEntityVO projectVO = projectmap.get(new BigInteger(oid));
//            if (CollUtil.isNotEmpty(attributeVOS)) {
//                for (AttributeVO attributeVO : attributeVOS) {
//                    if ("PersonCharge".equals(attributeVO.getAttributeEnName())) {
//                        projectVO.setPersonCharge(attributeVO.getAttributeValuex());
//                    } else if ("RecoveryPlan".equals(attributeVO.getAttributeEnName())) {
//                        projectVO.setRecoveryPlan(attributeVO.getAttributeValuex());
//                    } else if ("PostponedClassification".equals(attributeVO.getAttributeEnName())) {
//                        projectVO.setExtensionClassification(attributeVO.getAttributeValuex());
//                    } else if ("ReasonFor".equals(attributeVO.getAttributeEnName())) {
//                        projectVO.setReasonPostponement(attributeVO.getAttributeValuex());
//                    }
//                }
//            }
//            projectVO.setPhasePlan(typpmActiveTreeDTO.getName());
//            projectVO.setPhaseAccomplishDate(typpmActiveTreeDTO.getFinishDate());
//        }
//        List<String> projectNameList = Arrays.asList("ProjectDevelopmentOrder");
//        Map<String, List<AttributeVO>> ibaValue = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(projectOidList, TableTypeConstrant.TY_PROJECT_TYPE, projectNameList);
//        //给项目添加开发令字段
//        for (String oid : ibaValue.keySet()) {
//            ProjectEntityVO projectEntityVO = projectmap.get(new BigInteger(oid));
//            if (ObjectUtil.isNotNull(projectEntityVO)) {
//                projectEntityVO.setDevOrder(ibaValue.get(oid).get(0).getAttributeValuex());
//            }
//        }
//
//
//        return proceeds;
//    }



    //修改项目看板我的项目字段
    @Around("execution(* com.hustcad.plm.rpm.project.service.impl.TyppmProjectServiceImpl.queryProjectPageByCondition(..)))")
    public PageInfo<ProjectVO>  updateProjectBoardAOP(ProceedingJoinPoint joinPoint) throws Throwable {

        PageInfo<ProjectVO> proceeds = (PageInfo<ProjectVO>) joinPoint.proceed();
        List<ProjectVO> projectEntityVOList = proceeds.getList();
        Map<String, ProjectVO> projectMap = projectEntityVOList.stream()
                .collect(Collectors.toMap(
                        ProjectVO::getOid,
                        item -> item,
                        (oldValue, newValue) -> oldValue
                ));
        List<BigInteger> projectOidList = proceeds.getList().stream()
                .map(ProjectVO::getOid)
                .filter(Objects::nonNull)
                .map(BigInteger::new)
                .collect(Collectors.toList());
        List<TyppmPlan> planList = baseLinePlanExpandMapper.selectPlanByContainerOid(projectOidList);
        Map<String,TyppmActiveTreeDTO> activeTreeDTOMap = new HashMap<>();
        LocalDateTime now = LocalDateTime.now();
        for (TyppmPlan typpmPlan : planList) {
            Map<String, Object> params = new HashMap<>();
            params.put("rootOID", typpmPlan.getOid());
            params.put("rootOTYPE", TableTypeConstrant.TY_PJ_PLAN_OTYPE);
            params.put("markfordelete", 0L);
            List<TyppmActiveTreeDTO> firstPlan = this.typpmPlanActiveService.getLevelOnePlanActiveTreeByPlan(params);
            Optional<TyppmActiveTreeDTO> matchingDTO = firstPlan.stream()
                    .filter(dto -> {
                        LocalDateTime start = dto.getEarlyStart();
                        LocalDateTime finish = dto.getEarlyFinish();
                        return start != null && finish != null &&
                                start.isBefore(now) && finish.isAfter(now);
                    })
                    .findFirst();

            matchingDTO.ifPresent(result -> activeTreeDTOMap.put(typpmPlan.getContainerOID(), result));
        }
        List<BigInteger> nowPlanStageOid = activeTreeDTOMap.values().stream().map(TyppmActiveTreeDTO::getOid).filter(Objects::nonNull).map(BigInteger::new).collect(Collectors.toList());
        List<String> attrNameList = Arrays.asList("PersonCharge","RecoveryPlan","PostponedClassification","ReasonFor");
        Map<String, List<AttributeVO>> ibaValueMap = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(nowPlanStageOid, TableTypeConstrant.TY_JOB_OTYPE, attrNameList);
        for (String oid : activeTreeDTOMap.keySet()){
            TyppmActiveTreeDTO typpmActiveTreeDTO = activeTreeDTOMap.get(oid);
            List<AttributeVO> attributeVOS = ibaValueMap.get(typpmActiveTreeDTO.getOid());
            ProjectVO projectVO = projectMap.get(new BigInteger(oid));
            if (ObjectUtil.isNotNull(projectVO)) {

                if (CollUtil.isNotEmpty(attributeVOS)) {
                    for (AttributeVO attributeVO : attributeVOS) {
                        if ("PersonCharge".equals(attributeVO.getAttributeEnName())) {
                            projectVO.setPersonCharge(attributeVO.getAttributeValuex());
                        } else if ("RecoveryPlan".equals(attributeVO.getAttributeEnName())) {
                            projectVO.setRecoveryPlan(attributeVO.getAttributeValuex());
                        } else if ("PostponedClassification".equals(attributeVO.getAttributeEnName())) {
                            projectVO.setExtensionClassification(attributeVO.getAttributeValuex());
                        } else if ("ReasonFor".equals(attributeVO.getAttributeEnName())) {
                            projectVO.setReasonPostponement(attributeVO.getAttributeValuex());
                        }
                    }
                }
                projectVO.setPhasePlan(typpmActiveTreeDTO.getName());
                projectVO.setPhaseAccomplishDate(typpmActiveTreeDTO.getFinishDate());
            }
        }
        List<String> projectNameList = Arrays.asList("ProjectDevelopmentOrder");
        Map<String, List<AttributeVO>> ibaValue = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(projectOidList, TableTypeConstrant.TY_PROJECT_TYPE, projectNameList);
        //给项目添加开发令字段
        for (String oid : ibaValue.keySet()) {
            ProjectVO projectVO = projectMap.get(oid);
            if (ObjectUtil.isNotNull(projectVO)) {
                projectVO.setDevOrder(ibaValue.get(oid).get(0).getAttributeValuex());
            }
        }
        return proceeds;
    }


    //修改项目看板-项目任务返回字段
//    @Around("execution(* com.hustcad.plm.rpm.service.impl.job.TyppmJobServiceImpl.queryJobPageByParamsChildMark(..)))")
//    public PageInfo<TyppmJobDTO>  updateMyProjectTaskAOP(ProceedingJoinPoint joinPoint) throws Throwable {
//        Object proceeds = joinPoint.proceed();
//
//        PageInfo<TyppmJobDTO> pageInfo = (PageInfo<TyppmJobDTO>) proceeds;
//        List<String> attrNameList = Arrays.asList("TaskProgress","DelayingMeasures");
//        List<BigInteger> ppmJobOid = pageInfo.getList().stream().map(dto -> new BigInteger(dto.getOid())).collect(Collectors.toList());
//        Map<String, List<AttributeVO>> ibaValueAttrMap = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(ppmJobOid, TableTypeConstrant.TY_JOB_OTYPE, attrNameList);
//        for (TyppmJobDTO projectVO : pageInfo.getList()) {
//            String projectVOOid = projectVO.getOid();
//            if (ibaValueAttrMap.containsKey(projectVOOid)) {
//                List<AttributeVO> attributeVOS = ibaValueAttrMap.get(projectVOOid);
//                if (CollUtil.isEmpty(attributeVOS)) {
//                    continue;
//                }
//                for (AttributeVO attributeVO : attributeVOS) {
//                    if ("TaskProgress".equals(attributeVO.getAttributeEnName())) {
//                        projectVO.setTaskProgress(attributeVO.getAttributeValuex());
//                    } else if ("DelayingMeasures".equals(attributeVO.getAttributeEnName())) {
//                        projectVO.setDelayingMeasures(attributeVO.getAttributeValuex());
//                    }
//                }
//            }
//
//        }
//        return pageInfo;
//    }


    //项目恢复启动切入点
    @Around("execution(* com.hustcad.plm.rpm.project.controller.ProjectController.setProjectStateRecovery(..))")
    public Object setProjectStateStop(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String pjId = ((List)((RequestBase) proceedingJoinPoint.getArgs()[0]).getInput()).get(0).toString();
        rtTaskMapper.setProjectExecutionStatus(pjId);
        IBASaveParamDTO ibaSaveParamDTO = new IBASaveParamDTO();

        typlmCommonAttributeService.saveAttributeValue(ibaSaveParamDTO);
        Object proceed = proceedingJoinPoint.proceed();
        return proceed;
    }
    //项目终止改变状态
    @Before("execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.setProjectStateStop(..))")
    public void theProjectHasResumedAndStarted(JoinPoint joinPoint) throws Throwable {
        List<String> list=(List<String>)joinPoint.getArgs()[0];
        BigInteger executionStatusId = rtTaskMapper.selectExecutionStatus("执行状态");
        if (executionStatusId != null&&list.size()>0) {
            for (String pjId : list) {
                BigInteger projectOid = new BigInteger(pjId);
                rtTaskMapper.updateExecutionStatus("已终止",projectOid, executionStatusId);
            }
        }


    }
    //禁止删除模板导入的交付规则
    @Around(value = "execution(* com.hustcad.plm.rpm.controller.outrule.OutRuleController.deleteOutRule(..))")
    public Object deleteOutRuleTemplate(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //模板禁止删除交付规则的方法
        String oid = (String) proceedingJoinPoint.getArgs()[0];
        if (ObjectUtil.isNotEmpty(rtOutRuleMapper.selectOutRuleIsNew(oid))) {
            //通过传入的交付物的oid查询出任务oid
            BigInteger jobOidBigInteger = rtOutRuleMapper.selectJobOidByRuleOid(oid);
            String jobOid = jobOidBigInteger.toString();
            //通过任务oid查询计划oid
            BigInteger planOidBigInteger = rtProjectMapper.selectPlanOidByOid(jobOid);
            String planOid = "";
            if (planOidBigInteger != null) {
                planOid = planOidBigInteger.toString();
            }else {
                return proceedingJoinPoint.proceed();
            }
            //通过计划oid查询计划模板oid
            List<BigInteger> templateOidBigInteger = rtProjectsTemplateMapper.selectTemplateValueByOId(planOid);
            BigInteger isTemplate=rtProjectsTemplateMapper.selectIsTemplate(planOidBigInteger);
            if (isTemplate.equals("2")){
                return proceedingJoinPoint.proceed();
            }
            //String templateId = "";
            if (templateOidBigInteger != null) {
                //templateId = templateOidBigInteger.get(0).toString();
                throw RTErrorCodeEnum.OUTRULE_DELETE_ERROR.getException("模板禁止删除交付规则");
            }
//            if (ObjectUtil.isEmpty(templateId)) {
//            }
        }
        return proceedingJoinPoint.proceed();
    }
    @Around(value="execution(* com.hustcad.plm.rpm.controller.outrule.OutRuleController.deleteOutRule(..))")
    public Object deleteOutRule(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        String oid=(String)proceedingJoinPoint.getArgs()[0];
        Object proceed = proceedingJoinPoint.proceed();
        rtTaskMapper.deleteOutRule(oid);
        rtTaskMapper.deleteJobDeleverLink(oid);
        return proceed;
    }
    @Around(value="execution(* com.hustcad.plm.rpm.controller.outrule.OutRuleController.deleteOutRuleDeliver(..))")
    public Object deleteOutRuleDeliver(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            throw new RuntimeException("属性异常");
        }
        String jobOid = attributes.getRequest().getParameter("jobOid");
        if (StringUtils.isEmpty(jobOid)) {
            return null;
        }
        String linkOid=(String)proceedingJoinPoint.getArgs()[1];
        String objid=rtTaskMapper.selectOBJIdInDeliverlink(linkOid);
        rtTaskMapper.deleteJobDeleverLinkByabID(jobOid,objid);
        return proceedingJoinPoint.proceed();
    }
    @Around(value="execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.queryProjectAdvancedSearch(..))")
    public Object changeProjectCategory(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        PageInfo<ProjectEntityVO> pageInfo=(PageInfo<ProjectEntityVO>) proceedingJoinPoint.proceed();
        pageInfo.getList().forEach(projectEntityVO -> {
            if (projectEntityVO.getTypeDefName().equals("项目")){
                projectEntityVO.setTypeDefName(projectEntityVO.getCategory());
            }
        });
        return pageInfo;
    }

//删除项目时删除开发令关联
    @Around(value="execution(* com.hustcad.plm.rpm.project.service.TyppmProjectService.deleteProjectList(..))")
    public Object deleteDevelopmentOrder(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        List<String> list=(List<String>)proceedingJoinPoint.getArgs()[0];
        for (String pjId : list){
            String name = rtProjectMapper.selectProjectNameByProjectOid(pjId);
            Map<String, String> stringStringMap = rtProjectMapper.selectDevelopmentOrderByProjectName(name);
            if (CollUtil.isEmpty(stringStringMap)){
                continue;
            }
            String code = stringStringMap.get("PROJECT_CODE");
            if (StrUtil.isNotBlank(code)) {
                rtProjectMapper.deleteDevelopmentOrder(code);
            }
        }
        return proceedingJoinPoint.proceed();
    }
//导入EXCEL提示
    @Around(value="execution(* com.hustcad.plm.rpm.controller.plan.PlanActiveController.importSubPlanActiveByExcel(..))")
    public Object ImportInfo(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        MultipartFile multipartFile=(MultipartFile)proceedingJoinPoint.getArgs()[1];
        long count = getExcelDataCount(multipartFile);
        TyppmResponseResult<JSONArray> result=(TyppmResponseResult<JSONArray>) proceedingJoinPoint.proceed();
        String  data= result.getData().toString();
        JSONArray jsonArray = JSONArray.parseArray(data);
        int size = jsonArray.size();
        int totalChildrenCount = 0; // 记录所有 children 元素的总个数


        totalChildrenCount = countAllNestedChildren(jsonArray);
        size=size+totalChildrenCount;
        String message = "导入成功";
if(count!=size) {
    String successValue = "需要导入" + String.valueOf(count) + "条数据";
    String Value = "实际导入" + String.valueOf(size) + "条数据";
    message = "导入成功，" + successValue + "，" + Value;
}
        result.setMessage(message);
        return result;
    }
    @Around(value="execution(* com.hustcad.plm.rpm.controller.plan.PlanActiveController.importPlanActiveByExcel(..))")
    public Object ImportPJInfo(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        MultipartFile multipartFile=(MultipartFile)proceedingJoinPoint.getArgs()[0];
        long count = getExcelDataCount(multipartFile);
        TyppmResponseResult<JSONArray> result=(TyppmResponseResult<JSONArray>) proceedingJoinPoint.proceed();
        String  data= result.getData().toString();
        JSONArray jsonArray = JSONArray.parseArray(data);
        int size = jsonArray.size();
        int totalChildrenCount = 0; // 记录所有 children 元素的总个数


        totalChildrenCount = countAllNestedChildren(jsonArray);
        size=size+totalChildrenCount;
        String message = "导入成功";
        if(count!=size) {
            String successValue = "需要导入" + String.valueOf(count) + "条数据";
            String Value = "实际导入" + String.valueOf(size) + "条数据";
            message = "导入成功，" + successValue + "，" + Value;
        }
        result.setMessage(message);
        return result;
    }


    private int countAllNestedChildren(JSONArray array) {
        int total = 0;
        if (array == null) {
            return total; // 避免空指针
        }

        for (Object obj : array) {
            if (obj instanceof JSONObject) {
                JSONObject jsonObj = (JSONObject) obj;
                // 检查当前对象是否包含children字段，且为JSONArray
                if (jsonObj.containsKey("children")) {
                    Object children = jsonObj.get("children");
                    if (children instanceof JSONArray) {
                        JSONArray childArray = (JSONArray) children;
                        total += childArray.size(); // 累加当前层级children的个数
                        total += countAllNestedChildren(childArray); // 递归统计子层级children
                    }
                }
            }
        }
        return total;
    }
    @Around(value="execution(* com.hustcad.plm.rpm.template.controller.ProjectTemplateLibController.getChildrenByParent(..))")
    public Object getChildrenByParent(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            throw new RuntimeException("属性异常");
        }
        TyppmResponseResult<List<EntityBase>> result =(TyppmResponseResult<List<EntityBase>>) proceedingJoinPoint.proceed();

        String isTemplate = attributes.getRequest().getParameter("temp");
        if (StrUtil.isNotBlank(isTemplate) && isTemplate.equals("2")){
            return result;
        }

        String projectId = attributes.getRequest().getParameter("projectId");
        if (StringUtils.isNotBlank(projectId)){
            String parentOID = attributes.getRequest().getParameter("parentOID");
            List<EntityBase> data = result.getData();
            Map<String, Map<String, String>> map = rtProjectMapper.selectAttributeAndValues(projectId);
            if (Objects.isNull(map.get("PushMode"))||Objects.isNull(map.get("DevelopmentLevel"))){
                return  result;
            }

            String pushMode = "";
            if (map.containsKey("PushMode")){
                pushMode=map.get("PushMode").get("ATTRIBUTEVALUE");
            }else if (map.containsKey("pushMode")){
                pushMode=map.get("pushMode").get("ATTRIBUTEVALUE");
            }else {
                return result;
            }
            if (pushMode.equals("快开")){
                pushMode="QuickOpen";
            }else if (pushMode.equals("常规")){
                pushMode="Convention";
            }
            String developmentLevel = "";
            if (map.containsKey("DevelopmentLevel")){
                developmentLevel=map.get("DevelopmentLevel").get("ATTRIBUTEVALUE");
            }else if (map.containsKey("developmentLevel")){
                developmentLevel=map.get("developmentLevel").get("ATTRIBUTEVALUE");
            }else {
                return result;
            }
            if (parentOID.equals("-1")){
                List<String> strings = rtProjectMapper.selectSubfolderByPushModeAndDevelopmentLevel(developmentLevel.contains("Grade")?developmentLevel:"Grade"+developmentLevel, pushMode);
                List<EntityBase> newData = data
                        .stream()
                        .filter(f -> strings.contains(f.getOid()))
                        .filter(f->((SubFolder)f)
                                .getName()
                                .contains("任务模板库"))
                        .collect(Collectors.toList());
                result.setData(newData);
            }else {
                List<String> strings = rtProjectMapper.selectTemplateIdByPushModeAndDevelopmentLevel(
                        "Grade" + developmentLevel, pushMode);

                for (EntityBase datum : data) {
                    if (datum.getOtype().equals("ty.projectmng.admin.CTyProjectTemplate")){
                        List<Map<String, String>> maps = rtProjectMapper.selectTemplatePushModeAndDevelopmentLevelisNon(
                                datum.getOid());
                        if (maps.size()<2){
                            strings.add(datum.getOid());
                        }
                    }
                }
                List<EntityBase> newData=data.stream().filter(f -> strings.contains(f.getOid()) || f.getOtype().equals("ty.inteplm.folder.CTySubFolder") || strings.contains(f.getOid())).collect(Collectors.toList());

                result.setData(newData);
            }
            return result;
        }
        return result;
    }
    // 读取Excel并返回数据总条数（不包含表头）
    public int getExcelDataCount(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件为空");
        }

        // 用于计数的容器（通过匿名监听器统计行数）
        final int[] count = {0};

        try (InputStream inputStream = file.getInputStream()) {
            // 读取Excel，不映射实体类（适合任意格式Excel）
            EasyExcel.read(inputStream)
                    .headRowNumber(3) // 表头行数（默认1行，根据实际调整）
                    .sheet() // 读取第一个sheet
                    .registerReadListener(new com.alibaba.excel.read.listener.ReadListener<Object>() {
                        @Override
                        public void invoke(Object data, com.alibaba.excel.context.AnalysisContext context) {
                            // 每读取一行数据，计数器+1
                            count[0]++;
                        }

                        @Override
                        public void doAfterAllAnalysed(com.alibaba.excel.context.AnalysisContext context) {
                            // 读取完成后无需操作
                        }
                    })
                    .doRead(); // 执行读取
        }

        return count[0];
    }
}